//    Copyright 2008,2009 Paul Jorgensen
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "StdAfx.h"
#include "pf_ParseString2.h"
#include "pc_ParamBase.h"
#include "pc_ParamToken.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// instantiate a class object of pf_ParseString
// 
pf_ParseString po_CmdLineTokens;

// you can also instantiate with new for scope etc but class references will have to be changed
//pf_ParseString* po_CmdLineTokens = new pf_ParseString;

extern CString sCmdLine1;

extern int pi_NumCmds;     // for OOP param cmd execution
extern pc_ParamBase *po_ParamBaseCmds[10];		// an array of cmd objects to initialize for the parameter list


pf_ParseString::pf_ParseString(void)
{
	SlashPSet = FALSE;      // set slashp found flag to false 
	SlashTSet = FALSE;      // set slasht found flag to false 
	SlashWSet = FALSE;      // set slashw found flag to false 
	pg_SlashPTotalError = FALSE;
	pcArgChar = '/';   // default argument delimiter is slash, functions will be setup to set it to a different char
	piCurTokensFound=0;  // total of tokens found in commandline
	
	pf_SetupCmdParams();     // setup OOP cmd params
}

pf_ParseString::~pf_ParseString(void)
{
}

// a function to parse tokens in a CString
int pf_ParseString::pf_ParseTokens(wchar_t * pchp_StringToParse)
{
	
	CString psCmdLine;
	int piStrLen=0;
	int piStrParsePosition=0;
	
	int piCount=0;
	CString psTemp;
	char buffer[30];  // just for itoa conversion

	psCmdLine.Append(pchp_StringToParse);    // copy cmdline to CString ps_teststr
	piStrLen=psCmdLine.GetLength();         // ge the length for loop constraint

	psTemp = "this is input to ParseTokens-> ";
	psTemp += pchp_StringToParse;
	//AfxMessageBox(psTemp);
	
	// main while loop parse of cmdline string
	while( (psCmdLine[piStrParsePosition] != NULL ) && (piStrParsePosition <= piStrLen)) 
	{
		
	    //Call FindArgChar to search for poCmdLineTokens.pcArgChar - default is '/'
		piStrParsePosition = pf_FindArgChar(psCmdLine,piStrParsePosition,piStrLen);    // default search char is '/' as specified by poCmdLineTokens.pcArgChar
		if(piStrParsePosition != -1 )
		{ 
			// diagnostic condition test -> enable commented code to use
			if(psCmdLine[piStrParsePosition] == ' ')
			 {
				 psTemp.Empty();
				 psTemp = "The current character is a space!->position is->";
				 psTemp += _itoa(piStrParsePosition,buffer,10);
				 //AfxMessageBox(psTemp);
				 //break;
			 }
			// parse token while loop - until space,null or end of cmdline string
		     while((psCmdLine[piStrParsePosition] != ' ')  && (piStrParsePosition <= piStrLen ) && (psCmdLine[piStrParsePosition] != NULL ))
		     {
               // retrieve quoted string condition
		       if(psCmdLine[piStrParsePosition] == '"')
			   {
				 piStrParsePosition=pf_RetrieveQuotedStringTwo(psCmdLine,piStrParsePosition,piStrLen,piCurTokensFound);
			   }

			   // add the current character to the current token and increment the count
		       if(psCmdLine[piStrParsePosition] != NULL && psCmdLine[piStrParsePosition] != '"')
			   {
					   po_CmdLineTokens.psToken[piCurTokensFound].AppendChar(psCmdLine[piStrParsePosition]);
			   }

			   if(psCmdLine[piStrParsePosition] != NULL) piStrParsePosition++;
			   
		    }
			 
		}

		else AfxMessageBox(_T("Error finding cmd character - ensure all arguments are prefaced by the forward slash character"));
		if(psCmdLine[piStrParsePosition] != NULL ) piStrParsePosition++;
	}

	po_CmdLineTokens.pf_Setpi_NumTotalTokensFound(piCurTokensFound);   // record # of tokens found in parsestring object
	
	// add the resulting tokens to the final token array - TokenResultFinal - psCstrArrCount = total tokens found
	for(piCount=1;piCount<=piCurTokensFound;piCount++)
	{
		// record the tokens found into a global CString array
		po_CmdLineTokens.TokenResultFinal[piCount] += po_CmdLineTokens.psToken[piCount];
		// 
		//AfxMessageBox(psToken[piCount]);  // uncomment to see cmdline args retrieved
	}
	// if the token count is greater then 0 return sucess code ( should be TRUE ), otherwise return 0 ( should be FALSE )
	if(piCount > 0) return 1;

	return 0;
}

int pf_ParseString::pf_FindArgChar(CString psCmdlineParam,int piStrParsePosCopy, int piStrLenCopy)
{
	CString psTemp;
	char buffer[30];  // just for itoa conversion

	psTemp = "this is input to pf_FindArgChar-> ";
	psTemp += psCmdlineParam;
	//AfxMessageBox(psTemp);

	//while((*psCmdlineParam[piStrParsePosCopy] != NULL) && (piStrParsePosCopy < piStrLenCopy))
	while((piStrParsePosCopy < piStrLenCopy))
   {
      if(psCmdlineParam[piStrParsePosCopy] == po_CmdLineTokens.pcArgChar )  //  the default char is '/', pcArgChar is a member of the pf_ParseString Class
      {
		 //AfxMessageBox(_T("found Arg Char - /"));
		 piCurTokensFound++;      // increment current tokens found - this is why token array starts at 1 not 0 - first token found before stored and ++'d to 1
         return piStrParsePosCopy;
      }
      //else if ((*psCmdlineParam[piStrParsePosCopy] == NULL) || (piStrParsePosCopy >= piStrLenCopy))
      //{
      //   AfxMessageBox(_T("Error in pf_FindArgChar - /"));
      //   return -1;          // there has been an error  
      // }
      else
      {
         piStrParsePosCopy++;
		 //psTemp = "findargchar->";
		 //psTemp.AppendChar(psCmdlineParam[piStrParsePosCopy]);
		 //psTemp +=" incrementing parse count ->";
		 //psTemp += _itoa(piStrParsePosCopy, buffer,10);
		 //AfxMessageBox(psTemp);


	  }
   }
	return piStrParsePosCopy;
    
}



int pf_ParseString::pf_RetrieveQuotedStringTwo(CString psCmdlineParam,int piStrParsePosCopy, int piStrLenCopy, int piCurTokensFoundParam)
{
   CString psTemp;
   char buffer[30];  // just for itoa conversion
   //CString psReturnToken;

   int i, j;

   if( psCmdlineParam[piStrParsePosCopy] == '"')
   {
     piStrParsePosCopy++;            // move to first char of quoted string
	 
     while( psCmdlineParam[piStrParsePosCopy] != '"')  // until next quote
     {
       if(psCmdlineParam[piStrParsePosCopy] == NULL || piStrParsePosCopy >= piStrLenCopy )
       {
         AfxMessageBox(_T("retrieve quoted string 2 error - end quote not found before end of string"));
         exit(100);
       }
	   // add character to token and increment count
       po_CmdLineTokens.psToken[piCurTokensFoundParam].AppendChar(psCmdlineParam[piStrParsePosCopy]);
	   
       piStrParsePosCopy++;
     }
   }
   
   else{
	   AfxMessageBox(_T("RQS2 Error - quote not found"));

   }
   

   return piStrParsePosCopy;
}






// return a token string from the token array
CString pf_ParseString::pf_GetToken(int TokenNumber)
{
	return po_CmdLineTokens.TokenResultFinal[TokenNumber];
}

// return the total tokens that were found
int pf_ParseString::GetTokenTotal(void)
{
	return po_CmdLineTokens.pf_Getpi_NumTotalTokensFound();
}

int pf_ParseString::fParseCommandline_pComboxBox(CDialog* pparam_dlg)
{
	CString sTempString1;
	int result,countlocal=0;
	
	// call the parse tokens method
	result=pf_ParseString::pf_ParseTokens(sCmdLine1.GetBuffer());
	if( result==1)  // if tokens found
	{
		// for each token - send it to the dispatch method
		// added <= instead of = feb 2012 - not detecting 1 arg with count changes ( ie 0 to 1 )
		for(countlocal=1;countlocal <= pf_ParseString::GetTokenTotal();countlocal++)
		{
			//AfxMessageBox(_T("running pf_CmdDispatch for each token"));
			//result=pf_CmdDispatch(pf_ParseString::pf_GetToken(countlocal));
			result=pf_OOPDispatch(pf_ParseString::pf_GetToken(countlocal));
		}
	}
	
	return result;
}

int pf_ParseString::pf_OOPDispatch(CString ps_TokenParam)
{
	int countlocal;
	CString psTemp;

	for(countlocal=0;countlocal < pi_NumCmds;countlocal++)
	{		
		if(po_ParamBaseCmds[countlocal]->pc_CmdToken == ps_TokenParam.GetAt(1))
		{
			po_ParamBaseCmds[countlocal]->pf_ExecuteCmd(ps_TokenParam);
			
		}
	}
	return 1;
}

// When this function is called it determines the token and fires off the processing 
// function for that token.
int pf_ParseString::pf_CmdDispatch(CString ps_TokenParam)
{
	CString sTempString3;
	sTempString3 ="default def";
	int result;
	// get char after slash - this is switch
	// should possibly parse/check for slash first
	switch(ps_TokenParam.GetAt(1))
	{
		case 'p':
			sTempString3 ="found p parameter!";
			//AfxMessageBox(sTempString3);
			result=pf_Process_SlashP(ps_TokenParam); // this result no longer affects running - SlashPSet variable does now
			return result;
		case 'h':
			sTempString3 ="found h parameter!";
			//AfxMessageBox(sTempString3);
			pf_Process_SlashH(ps_TokenParam);
			break;
		case 'w':
			sTempString3 ="found w parameter!";
			//AfxMessageBox(sTempString3);
			pf_Process_SlashW(ps_TokenParam);
			break;
		case 't':
			sTempString3 ="found t parameter!";
			//AfxMessageBox(sTempString3);
			pf_Process_SlashT(ps_TokenParam);
			break;
		default:
			sTempString3 ="no parameter found at position 1 (2)";
			sTempString3.Append(ps_TokenParam);
			// right now no messagebox means the app ignores unknown arguments
			//AfxMessageBox(sTempString3);
			break;
		
	}
	return 0;
}
// process set pcombobox items
int pf_ParseString::pf_Process_SlashP(CString ps_TokenParam)
{
	CString sTempString2[20];
	int pi_strlen2=0,count2=0,count3=0;
	wchar_t parsetest;
	CString sMessage1;
	
	CComboBox* pp_ComboBox; // this is a pointer to object of type CComboBox
	
	pi_strlen2=ps_TokenParam.GetLength();

	count2=3;  // bypass switch part of token, we know its a /p: switch
	//while((count2 <= pi_strlen2) && (ps_TokenParam.GetAt(count2) != NULL)){
		while((count2 <= pi_strlen2) && (ps_TokenParam.GetAt(count2) != NULL)){
			parsetest=ps_TokenParam.GetAt(count2);
			if(parsetest != ','){
			  TokenStrings_SlashP[count3].AppendChar(ps_TokenParam.GetAt(count2));
			  count2++;
			}
			else{
				count2++;
				count3++;
			}
		}
		
	po_CmdLineTokens.pf_Setpi_SlashPTotal(count3);
	po_CmdLineTokens.pf_SetSlashPSet(TRUE);	
	
	if(po_CmdLineTokens.pf_Getpi_SlashPTotal() >= 15) {
		sMessage1 += "Error - More then 15 list items, reverting to default, please advise your administrator";
	  AfxMessageBox(sMessage1);
	  po_CmdLineTokens.pf_Setpg_SlashPTotalError(TRUE);
	  
	  return 0;
	}
	return 1;
}

// process set height parameter
int pf_ParseString::pf_Process_SlashH(CString ps_TokenParam)
{
	return 0;
}
// process set title parameter
int pf_ParseString::pf_Process_SlashT(CString ps_TokenParam)
{
	CString sTempString2[20];
	int pi_strlen2=0,count2=0,count3=0;
	wchar_t parsetest;
	CString sMessage1;

    // Set the slashT variable via class instance
	po_CmdLineTokens.pf_SetSlashTSet(TRUE);

	pi_strlen2=ps_TokenParam.GetLength();  // get length of token
	count2=3;  // bypass switch part of token
	
	//while((count2 <= pi_strlen2) && (ps_TokenParam.GetAt(count2) != NULL)){
		while((count2 <= pi_strlen2) && (ps_TokenParam.GetAt(count2) != NULL)){
			parsetest=ps_TokenParam.GetAt(count2);
			if(parsetest != ','){
			  po_CmdLineTokens.TokenStrings_SlashT[count3].AppendChar(ps_TokenParam.GetAt(count2));
			  count2++;
			}
			else{
				count2++;
				count3++;
			}
		}
		
	
	// Set the slashT variable via class instance - this is already set- March 29 2012
	//po_CmdLineTokens.pf_SetSlashTSet(TRUE);

	return 1;

	
}
// process dynamic button parameter
int pf_ParseString::pf_Process_SlashB(CString ps_TokenParam)
{
	return 0;
}
// process set width parameter
int pf_ParseString::pf_Process_SlashW(CString ps_TokenParam)
{

	po_CmdLineTokens.pf_SetSlashWSet(TRUE);   // action takes place in InitDialog

	

	return 0;
}

BOOL pf_ParseString::pf_GetSlashPSet(void)
{
	return po_CmdLineTokens.SlashPSet;
}

BOOL pf_ParseString::pf_GetSlashTSet(void)
{
	return po_CmdLineTokens.SlashTSet;
	
}

BOOL pf_ParseString::pf_GetSlashWSet(void)
{
	return po_CmdLineTokens.SlashWSet;
	
}

void pf_ParseString::pf_SetSlashPSet(BOOL SetSlashPParam)
{
	po_CmdLineTokens.SlashPSet=SetSlashPParam;
	
}
void pf_ParseString::pf_SetSlashTSet(BOOL SetSlashTParam)
{
	po_CmdLineTokens.SlashTSet=SetSlashTParam;
	
}

void pf_ParseString::pf_SetSlashWSet(BOOL SetSlashWParam)
{
	po_CmdLineTokens.SlashWSet=SetSlashWParam;
	
}

int pf_ParseString::pf_Getpi_SlashPTotal(void)
{
	return pi_SlashPTotal;
}

int pf_ParseString::pf_Setpi_SlashPTotal(int SetSlashPTotal)
{
	pi_SlashPTotal = SetSlashPTotal;
	return 0;
}

int pf_ParseString::pf_Getpi_ErrorLevel(void)
{
	return pi_ErrorLevel;
}

void pf_ParseString::pf_Setpi_ErrorLevel(int Setpi_ErrorLevel)
{
	pi_ErrorLevel = Setpi_ErrorLevel;
}

int pf_ParseString::pf_Getpi_NumTotalTokensFound(void)
{
	return pi_NumTotalTokensFound;
}

void pf_ParseString::pf_Setpi_NumTotalTokensFound(int Setpi_NumTotalTokensFound)
{
	pi_NumTotalTokensFound = Setpi_NumTotalTokensFound;
}

void pf_ParseString::pf_Setpg_SlashPTotalError(BOOL Setpg_SlashPTotalError)
{
	pg_SlashPTotalError = Setpg_SlashPTotalError;
}

BOOL pf_ParseString::pf_Getpg_SlashPTotalError(void)
{
	return pg_SlashPTotalError;
}

int pf_ParseString::pf_WriteResultRegistryItem(CString ps_ResultString)
{
	CWinApp* pApp = AfxGetApp();

	CString strSection       = _T("RData");
	CString strStringItem    = _T("PComboBox");
	CString strIntItem       = _T("Result");

	pApp->WriteProfileString(strSection, strStringItem, ps_ResultString);

	return 1;
	//return 0;
}


